import Taro, { Component, Config } from '@tarojs/taro'
import { connect } from '@tarojs/redux'
import { setHotelDate } from '../../../actions/hotel'
import { WEEK_LIST } from '../../../contans'
import { View, Text } from '@tarojs/components'
import Moment from '../../../utils/moment'
import './index.styl'
const CURRENT_DATE: string = Moment(new Date()).format('YYYY-MM-DD')
const TOMORROW_DATE: string = Moment(new Date()).add(1, 'day').format('YYYY-MM-DD')

interface WeekItem {
  name: string,
  active: boolean
}
interface dateListItem {
  date: string,
  date_format: string,
  desc: string,
  isWeek: boolean,
  is_disable: boolean, // 是不是能操作的数据
  sub?: string,
  week: string,
  is_active?: boolean,
  is_checkOutDate_active_gray?: boolean,
}
interface renderListItem {
  title: string,
  dateList: dateListItem[]
}
interface PageState {
  weeks: WeekItem[],
  renderList: renderListItem[],
  countNum: number,
  check_in_date: string,
  check_out_date: string,
  toDayDate: string,
  is_checkOutDate_active_gray: boolean,
  is_show_header_box_shadow: boolean,
}
interface PageDispatchProps {
  setHotelDate: (checkInDate: string, checkOutDate: string) => void
}
type PageOwnProps = {
  hotel: {
    checkInDate: string,
    checkOutDate: string
  }
}

interface HotelCanlendar {
  props: PageState & PageDispatchProps & PageOwnProps
}

@connect(({ hotel: { checkInDate, checkOutDate } }) => ({
  hotel: {
    checkInDate,
    checkOutDate
  }
}), dispatch => ({
  setHotelDate (checkInDate, checkOutDate) {
    dispatch(setHotelDate(checkInDate, checkOutDate))
  }
}))

class HotelCanlendar extends Component {
  constructor() {
    super(...arguments)
  }
  state: PageState = {
    weeks: [],
    renderList: [],
    countNum: 0, // 不做页面逻辑
    check_in_date: '',
    check_out_date: '',
    toDayDate: '',
    is_checkOutDate_active_gray: false,
    is_show_header_box_shadow: false
  }
  config: Config = {
    navigationBarTitleText: '选择日期'
  }
  componentDidMount() {
    this.state.countNum = 0
    const { checkInDate, checkOutDate } = this.props.hotel
    const setWeeks: any[] = WEEK_LIST.map(i => ({ name: i, active: ['日', '六'].includes(i) }))

    this.setState({
      toDayDate: CURRENT_DATE,
      check_in_date: checkInDate,
      check_out_date: checkOutDate,
      weeks: setWeeks
    }, () => this._initFn())
  }
  selectDate(dateItem: dateListItem, event) {
    event.stopPropagation()
    const { is_disable } = dateItem
    let checkedDate: string = dateItem.date_format
    let OriginRenderList: renderListItem[] = this.state.renderList
    let check_in_date: string = this.state.check_in_date
    let check_out_date: string = this.state.check_out_date

    if (is_disable) return

    const checkedDateValueOf: number = this._getValueOf(checkedDate)
    const checkInValueOf: number = this._getValueOf(check_in_date)
    const checkOutValueOf: number = this._getValueOf(check_out_date)

    const is_checked_before_checkInDate: boolean = checkedDateValueOf < checkInValueOf
    const is_checked_checkInDate: boolean = checkedDateValueOf === checkInValueOf
    const is_checked_between: boolean = checkedDateValueOf > checkInValueOf && checkedDateValueOf < checkOutValueOf
    const is_checked_checkOutDate: boolean = checkedDateValueOf === checkOutValueOf
    const is_checked_after_checkOutDate: boolean = checkedDateValueOf > checkOutValueOf
    
    let is_checkOutDate_active_gray: boolean = this.state.is_checkOutDate_active_gray

    // 1. 判断 超前
    // 2. 判断 check in
    // 2. 判断 between
    // 2. 判断 check out
    
    if (is_checked_before_checkInDate) {
      check_in_date = checkedDate
      is_checkOutDate_active_gray = true
    } else if (is_checked_checkInDate && is_checkOutDate_active_gray) {
      is_checkOutDate_active_gray = false
    } else if (is_checked_checkInDate && !is_checkOutDate_active_gray) {
      is_checkOutDate_active_gray = true
      check_out_date = Moment(new Date(check_in_date)).add(1, 'day').format('YYYY-MM-DD')
    } else if (is_checked_between) {
      is_checkOutDate_active_gray = false
      check_out_date = checkedDate
    } else if (is_checked_checkOutDate && is_checkOutDate_active_gray) {
      is_checkOutDate_active_gray = false
      check_out_date = checkedDate
    } else if (is_checked_checkOutDate && !is_checkOutDate_active_gray) {
      is_checkOutDate_active_gray = true
      check_in_date = checkedDate
      check_out_date = Moment(new Date(check_in_date)).add(1, 'day').format('YYYY-MM-DD')
    } else if (is_checked_after_checkOutDate && is_checkOutDate_active_gray) {
      is_checkOutDate_active_gray = false
      check_out_date = checkedDate
    } else if (is_checked_after_checkOutDate && !is_checkOutDate_active_gray) {
      is_checkOutDate_active_gray = true
      check_in_date = checkedDate
      check_out_date = Moment(new Date(check_in_date)).add(1, 'day').format('YYYY-MM-DD')
    }

    OriginRenderList.forEach(item => item.dateList.forEach(i => {
      const checkedInFlag = i.date_format === check_in_date
      const checkedOutFlag = i.date_format === check_out_date
      i.desc = ''
      i.is_active = checkedInFlag || checkedOutFlag
      i.is_checkOutDate_active_gray = false

      if (checkedInFlag) i.desc = '入住'
      if (checkedOutFlag) {
        i.desc = '离店'
        if (is_checkOutDate_active_gray) i.is_checkOutDate_active_gray = true
      }
    }))

    this.setState({ renderList: OriginRenderList, check_in_date, check_out_date, is_checkOutDate_active_gray })

    if (!is_checkOutDate_active_gray) {
      this.props.setHotelDate(check_in_date, check_out_date)
      const timer = setTimeout(() => {
        clearTimeout(timer)
        Taro.navigateBack()
      }, 300)
    }
  }
  onPageScroll({ scrollTop }) {
    const originIsShowHeaderBoxSadow = this.state.is_show_header_box_shadow
    
    if (scrollTop > 5 && !originIsShowHeaderBoxSadow) {
      this.setState({ is_show_header_box_shadow: true })
    } else if (scrollTop <= 5 && originIsShowHeaderBoxSadow) {
      this.setState({ is_show_header_box_shadow: false })
    }
  }
  _initFn() {
    const renderList: any[] = this._getRenderData(CURRENT_DATE)
    const checkedInDateMonth: number = new Date(this.state.check_in_date).getMonth() + 1
    const findIndex: number = renderList.findIndex(item => item.month === checkedInDateMonth)
    
    this.setState({ renderList }, () => {
      // 判断当前选中的月份，滚动到相应月份
      findIndex > 0 && Taro.createSelectorQuery().selectAll('.month-pannel').boundingClientRect().exec(monthList => {
        Taro.createSelectorQuery().select('.fixed-height-pannel').boundingClientRect().exec(fixedTop => {
          const fixedTopHeight: number =  fixedTop[0].height
          const scrollTop: number = monthList[0][findIndex].top - fixedTopHeight
          
          Taro.pageScrollTo({ scrollTop: scrollTop, duration: 0 })
        })
      })
    })
  }
  _getRenderData(date: string) {
    let returnList: any[] = []
    const currentYear: number = Number(date.substring(0, 4))
    const currentMonth: number = Number(date.substring(5, 7))
    const currentDate: number = Number(date.substring(8))
    let calcYear: number = currentYear
    let calcMonth: number = currentMonth
    let countDateNum = 0

    while (countDateNum < 90) {
      const totalMonthDays = this._GetMonthDays(calcYear, calcMonth)
      const jqList: any[] = this._getjq(calcYear)

      if (currentYear === calcYear && currentMonth === calcMonth) {
        countDateNum += (totalMonthDays - currentDate)
      } else {
        countDateNum += totalMonthDays
      }
      returnList.push({
        title: `${calcYear}年${this._add0(calcMonth)}月`,
        month: calcMonth,
        dateList: this._geMonthDateList(calcYear, calcMonth, totalMonthDays, jqList)
      })

      if (calcMonth === 12) {
        calcYear = calcYear += 1
        calcMonth = 1
      } else {
        calcMonth = calcMonth += 1
      }
    }
    return returnList
  }
  _geMonthDateList(year: number, month: number, countDateNum: number, jqList: any[]): any[] {
    let retList: dateListItem[] = []
    const beforeAddDateNum: number = new Date(`${year}/${month}/01`).getDay()
    const { check_in_date, check_out_date } = this.state

    for (let i = (1 - beforeAddDateNum); i <= countDateNum; i ++) {
      const cMonth: string = this._add0(month)
      const cDate: string = this._add0(i)
      const date_format: string = i < 1 ? '' : `${year}-${cMonth}-${cDate}`
      const week: string = new Date(date_format).getDay() + ''
      const isWeek: boolean = [0, 6].includes(Number(week))
      const is_disable: boolean = i < 1 || this.state.countNum > 90 ? true : this._getValueOf(date_format) < this._getValueOf(CURRENT_DATE)
      const is_active: boolean = [check_in_date, check_out_date].includes(date_format)
      let date: string = i < 1 ? '' : i + ''
      let desc: string = date_format === check_in_date ? '入住' : date_format === check_out_date ? '离店' : ''
      const sub: any =  i < 1 ? '' : (jqList.find(i => i.dateFormat === date_format) || {}).name

      if (i >= 1 && this._getValueOf(date_format) >= this._getValueOf(CURRENT_DATE)) (this.state.countNum = this.state.countNum += 1)
      if (date_format === CURRENT_DATE) {
        date = '今天'
      } else if (date_format === TOMORROW_DATE) {
        date = '明天'
      }

      retList.push({
        sub,
        isWeek,
        week,
        date,
        desc,
        date_format,
        is_disable,
        is_active
      })
    }
    return retList
  }
  _GetMonthDays(year: number, month: number): number { // 获取月份的总天数
    return new Date(year, month, 0).getDate()
  }
  _add0 (num: number): string {
    return String(num < 10 ? `0${num}` : num)
  }
  _getValueOf(date: string): number {
    return new Date(date.replace(/-/g, '/')).valueOf()
  }
  _getjq(year: number) {
    const calcYearNum: number = Number(String(year).substring(2))
    const divisions: any[] = [
      {
        name: '立春',
        C: 3.87,
        month: `${year}-02`,
        id: 0
      },
      {
        name: '雨水',
        C: 18.73,
        month: `${year}-02`,
        id: 1
      },
      {
        name: '惊蛰',
        C: 5.63,
        month: `${year}-03`,
        id: 2
      },
      {
        name: '春分',
        C: 20.646,
        month: `${year}-03`,
        id: 3
      },
      {
        name: '清明',
        C: 4.81,
        month: `${year}-04`,
        id: 4
      },
      {
        name: '谷雨',
        C: 20.1,
        month: `${year}-04`,
        id: 5
      },
      {
        name: '立夏',
        C: 5.52,
        month: `${year}-05`,
        id: 6
      },
      {
        name: '小满',
        C: 21.04,
        month: `${year}-05`,
        id: 7
      },
      {
        name: '芒种',
        C: 5.678,
        month: `${year}-06`,
        id: 8
      },
      {
        name: '夏至',
        C: 21.37,
        month: `${year}-06`,
        id: 9
      },
      {
        name: '小暑',
        C: 7.108,
        month: `${year}-07`,
        id: 10
      },
      {
        name: '大暑',
        C: 22.83,
        month: `${year}-07`,
        id: 11
      },
      {
        name: '立秋',
        C: 7.5,
        month: `${year}-08`,
        id: 12
      },
      {
        name: '处暑',
        C: 23.13,
        month: `${year}-08`,
        id: 13
      },
      {
        name: '白露',
        C: 7.646,
        month: `${year}-09`,
        id: 14
      },
      {
        name: '秋分',
        C: 23.042,
        month: `${year}-09`,
        id: 15
      },
      {
        name: '寒露',
        C: 8.318,
        month: `${year}-10`,
        id: 16
      },
      {
        name: '霜降',
        C: 23.438,
        month: `${year}-10`,
        id: 17
      },
      {
        name: '立冬',
        C: 7.438,
        month: `${year}-11`,
        id: 18
      },
      {
        name: '小雪',
        C: 22.36,
        month: `${year}-11`,
        id: 19
      },
      {
        name: '大雪',
        C: 7.18,
        month: `${year}-12`,
        id: 10
      },
      {
        name: '冬至',
        C: 21.94,
        month: `${year}-12`,
        id: 21
      },
      {
        name: '小寒',
        C: 5.4055,
        month: `${year}-01`,
        id: 22
      },
      {
        name: '大寒',
        C: 20.12,
        month: `${year}-01`,
        id: 23
      }
    ]
    
    const ret: any[] = divisions.map(({ name, month, C, id }) => {
      let date: number = parseInt(String(calcYearNum * 0.2422 + C)) - parseInt(String((calcYearNum - 1) / 4))

      // 处理边界情况
      if (id === 1 && year === 2026) date = date -= 1
      if (id === 3 && year === 2084) date = date += 1
      if (id === 6 && year === 1911) date = date += 1
      if (id === 7 && year === 2008) date = date += 1
      if (id === 9 && year === 1928) date = date += 1
      if (id === 10 && (year === 1925 || year === 2016)) date = date += 1
      if (id === 11 && year === 1922) date = date += 1
      if (id === 12 && year === 2002) date = date += 1
      if (id === 14 && year === 1927) date = date += 1
      if (id === 15 && year === 1942) date = date += 1
      if (id === 17 && year === 2089) date = date += 1
      if (id === 18 && year === 2089) date = date += 1
      if (id === 19 && year === 1978) date = date += 1
      if (id === 20 && year === 1954) date = date += 1
      if (id === 21 && (year === 1918 || year === 2021)) date = date += 1
      if (id === 22 && (year === 1982 || year === 2019)) date = date -= 1
      if (id === 23 && year === 2082) date = date += 1

      const dateFormat: string = `${month}-${this._add0(date)}`

      return {
        name,
        dateFormat
      }
    })
    return ret
  }
  render() {
    const { renderList, is_show_header_box_shadow } = this.state
    
    return (
      <View className='bg'>
        <View className={`fixed-top ${is_show_header_box_shadow ? 'active' : ''}`}>
          {this.state.weeks.map((i, index) => (
            <Text className={`${i.active ? 'active' : ''}`} key={index}>{i.name}</Text>
          ))}
        </View>
        <View className='fixed-height-pannel'></View>
        <View className='date-content'>
          {
            renderList.length && renderList.map((itemMonth, indexMonth) => (
              <View className='month-pannel' key={indexMonth + 'indexMonth'}>
                <View className='title'>{itemMonth.title}</View>
                <View className='date-list'>
                  {
                    itemMonth.dateList.map((dateItem, indexDate) => (
                      <View
                        className={`date-item ${dateItem.isWeek ? 'week' : ''} ${dateItem.is_disable ? 'disable' : ''} ${dateItem.is_active ? 'active' : ''} ${dateItem.is_checkOutDate_active_gray ? 'active-gard' : ''} `}
                        key={indexDate + 'indexDate'}
                        onClick={this.selectDate.bind(this, dateItem)}>
                        <Text className='sub'>{dateItem.sub}</Text>
                        <Text className='date'>{dateItem.date}</Text>
                        <Text className='desc'>{dateItem.desc}</Text>
                      </View>
                    ))
                  }
                </View>
              </View>
            ))
          }
        </View>
      </View>
    )
  }
}
export default HotelCanlendar